/*
*  Copyright 2019-2020 Zheng Jie
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package me.landery.modules.sinco.service.impl;

import me.landery.exception.BadRequestException;
import me.landery.modules.sinco.domain.Withdrawal;
import me.landery.modules.sinco.domain.em.WithDrawStatus;
import me.landery.modules.sinco.service.VipService;
import me.landery.modules.sinco.service.dto.VipDto;
import me.landery.modules.system.service.UserService;
import me.landery.modules.system.service.mapstruct.UserMapper;
import me.landery.utils.*;
import lombok.RequiredArgsConstructor;
import me.landery.modules.sinco.repository.WithdrawalRepository;
import me.landery.modules.sinco.service.WithdrawalService;
import me.landery.modules.sinco.service.dto.WithdrawalDto;
import me.landery.modules.sinco.service.dto.WithdrawalQueryCriteria;
import me.landery.modules.sinco.service.mapstruct.WithdrawalMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.*;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;

/**
* @website https://el-admin.vip
* @description 服务实现
* @author landery
* @date 2022-06-25
**/
@Service
@RequiredArgsConstructor
public class WithdrawalServiceImpl implements WithdrawalService {

    private final WithdrawalRepository withdrawalRepository;
    private final WithdrawalMapper withdrawalMapper;

    private final VipService vipService;
    private final UserService userService;
    private final UserMapper userMapper;



    @Override
    public Map<String,Object> queryAll(WithdrawalQueryCriteria criteria, Pageable pageable){
        Page<Withdrawal> page = withdrawalRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        return PageUtil.toPage(page.map(withdrawalMapper::toDto));
    }

    @Override
    public List<WithdrawalDto> queryAll(WithdrawalQueryCriteria criteria){
        return withdrawalMapper.toDto(withdrawalRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    @Transactional
    public WithdrawalDto findById(Long id) {
        Withdrawal withdrawal = withdrawalRepository.findById(id).orElseGet(Withdrawal::new);
        ValidationUtil.isNull(withdrawal.getId(),"Withdrawal","id",id);
        return withdrawalMapper.toDto(withdrawal);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public WithdrawalDto create(Withdrawal resources) {
        //获取当前登录是否存在正在申请的提现记录，如果有则不能再次申请提现
        Withdrawal withdrawal = withdrawalRepository.findByUserIdAndStatus(SecurityUtils.getCurrentUserId(), WithDrawStatus.APPLY.getValue());
        if (withdrawal != null) {
            throw new BadRequestException("已经存在正在申请的提现记录，请耐心等待审核");
        }

        //获取当前登录的用户的佣金
        VipDto vipDto = vipService.findByUserID(SecurityUtils.getCurrentUserId());
        if (vipDto.getProfit() < resources.getMoney()) {
            throw new BadRequestException("佣金不足，提现失败");
        }

        //新建提现记录
        Withdrawal withdrawalNew = new Withdrawal();
        withdrawalNew.setUser(userMapper.toEntity(userService.findById(SecurityUtils.getCurrentUserId())));
        withdrawalNew.setMoney(resources.getMoney());
        withdrawalNew.setStatus(WithDrawStatus.APPLY.getValue());
        withdrawalNew.setName(resources.getName());
        withdrawalNew.setAccount(resources.getAccount());
//        withdrawalRepository.save(withdrawalNew);

        //发送邮件通知用户提现申请已经提交

        return withdrawalMapper.toDto(withdrawalRepository.save(withdrawalNew));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Withdrawal resources) {
        Withdrawal withdrawal = withdrawalRepository.findById(resources.getId()).orElseGet(Withdrawal::new);
        ValidationUtil.isNull( withdrawal.getId(),"Withdrawal","id",resources.getId());

        if (!Objects.equals(withdrawal.getStatus(), WithDrawStatus.APPLY.getValue())) {
            throw new BadRequestException("提现记录已经审核，不能修改");
        }
        withdrawal.copy(resources);
        withdrawalRepository.save(withdrawal);

        if (Objects.equals(resources.getStatus(), WithDrawStatus.SUCCESS.getValue())){
            //扣钱
            vipService.updateProfit(SecurityUtils.getCurrentUserId(), -resources.getMoney());
        }

    }

    @Override
    public void deleteAll(Long[] ids) {
        for (Long id : ids) {
            withdrawalRepository.deleteById(id);
        }
    }

    @Override
    public void download(List<WithdrawalDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (WithdrawalDto withdrawal : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("提现人", withdrawal.getUser().getUsername());
            map.put("提现金额", withdrawal.getMoney());
            map.put("提现状态 0发起提现 1提现成功 2提现失败", withdrawal.getStatus());
            map.put("创建者", withdrawal.getCreateBy());
            map.put("更新者", withdrawal.getUpdateBy());
            map.put("创建日期", withdrawal.getCreateTime());
            map.put("更新时间", withdrawal.getUpdateTime());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }
}